home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 November: Tool Chest / Dev.CD Nov 96 TC / Dev.CD Nov 96 TC.toast / Sample Code / Snippets / QuickDraw / Band Copying the Sequel / Source / Band Copying the Sequel.c
Encoding:
C/C++ Source or Header  |  1996-09-17  |  10.8 KB  |  382 lines  |  [TEXT/CWIE]

  1. /****************************************************************************/
  2. /*                                                                            */
  3. /*    Application:    Band Copying the Sequel                                    */
  4. /*                                                                            */
  5. /*    File:            Band Copying the Sequel.π                                */
  6. /*                    Band Copying the Sequel.c                                */
  7. /*                    Band Copying the Sequel.π.rsrc                            */
  8. /*                                                                            */
  9. /*    Description:    Under low memory conditions, it's often necessary        */
  10. /*                    to draw an image by individual bands rather than        */
  11. /*                    to draw the entire image at once, and in most cases        */
  12. /*                    this method works fine unless the image requires        */
  13. /*                    dithering from its source to its destination.  The        */
  14. /*                    purpose of this app is to show the problem that may        */
  15. /*                    occur when copying these individual bands and to        */
  16. /*                    provide one possible solution.                            */
  17. /*                                                                            */
  18. /*    Programmer:        Edgar Lee                                                */
  19. /*    Organization:    Apple Computer, Inc.                                    */
  20. /*    Department:        Developer Technical Support, DTS                        */
  21. /*    Language:        C (Think C version 5.0.1)                                */
  22. /*    Date Created:    11-03-91                                                */
  23. /*                                                                            */
  24. /****************************************************************************/
  25.  
  26. #include <Dialogs.h>
  27. #include <Fonts.h>
  28. #include <Resources.h>
  29. #include <QDOffscreen.h>
  30. #include <TextUtils.h>
  31. /* Constant Declarations */
  32.  
  33. #define    WWIDTH        300        /* Window width for the color and b/w images. */
  34. #define    WHEIGHT        300        /* Window height for the color and b/w images. */
  35.  
  36. #define WLEFT        (((qd.screenBits.bounds.right - qd.screenBits.bounds.left) - WWIDTH) / 2)
  37. #define WTOP        (((qd.screenBits.bounds.bottom - qd.screenBits.bounds.top) - WHEIGHT) / 2)
  38.  
  39. #define TOTALBANDS    25        /* Total number of bands to separate Pict into. */
  40. #define    PADHEIGHT    8        /* Padding to add above band in pixels. */
  41. #define    SCALING        4        /* Scale source by factor of... */
  42.  
  43. /* Global Variable Definitions */
  44.  
  45. WindowPtr        gCWindow;
  46. WindowPtr        gWindow;
  47.  
  48. GWorldPtr        gGWorld;
  49. PixMapHandle    gPixMap;
  50.  
  51. PicHandle        gPict;                /* Pict resource used for test. */
  52. int                gPictWidth;            /* Width of pict resource. */
  53. int                gPictHeight;        /* Height of pict resource. */
  54. int                gBandStart;            /* Starting band number to draw. */
  55. int                gBandEnd;            /* Ending band number to draw. */
  56. int             gBandHeight;        /* Thickness of band in pixels. */
  57. int                gPadding = 0;        /* Current value of padding. */
  58.  
  59. void initMac();            /* Initializes the environment. */
  60. void initPictInfo();    /* Initializes the picture information. */
  61.  
  62. void createWindows();    /* Creates windows for color and b/w images. */
  63. void createGWorld();    /* Creates 1 bit offscreen GWorld used for dithering. */
  64. void drawCWindow();        /* Displays the original color image. */
  65. void drawBwWindow();    /* Displays the dithered/enlarged b/w image. */
  66. void doBandCopy();        /* Copies image by individual bands. */
  67. void doNoBandCopy();    /* Copies the entire image at once without bands. */
  68. void drawMessage();        /* Draws text in color window. */
  69.  
  70. void doEventLoop();        /* Handles all events. */
  71.  
  72. void main(void)
  73. {
  74.     initMac();
  75.     initPictInfo();
  76.  
  77.     createWindows();
  78.     createGWorld();
  79.     
  80.     doEventLoop();
  81. }
  82.  
  83. void initMac()
  84. {
  85.     MaxApplZone();
  86.     
  87.     InitGraf( &qd.thePort );
  88.     InitFonts();
  89.     InitWindows();
  90.     InitMenus();
  91.     TEInit();
  92.     InitDialogs( nil );
  93.     InitCursor();
  94.     FlushEvents( 0, everyEvent );    
  95. }
  96.  
  97. void initPictInfo()
  98. {
  99.     gPict = (PicHandle)GetResource( 'PICT', 128 );
  100.  
  101.     gPictWidth = (**gPict).picFrame.right - (**gPict).picFrame.left;
  102.     gPictHeight = (**gPict).picFrame.bottom - (**gPict).picFrame.top;
  103.     
  104.     gBandStart = 0;                                /* Start at band number 0. */
  105.     gBandEnd = 0;                                /* End at band number 0. */
  106.     gBandHeight = gPictHeight / TOTALBANDS;
  107. }
  108.  
  109. void createWindows()
  110. {
  111.     Rect rect;
  112.     
  113.     SetRect( &rect, WLEFT, WTOP, WLEFT + WWIDTH, WTOP + WHEIGHT );
  114.     
  115.     OffsetRect( &rect, -((WWIDTH + 10) / 2), 0 );
  116.     gCWindow = NewCWindow( 0L, &rect, "\pBand Copying the Sequel", true, documentProc,
  117.                             (WindowPtr)-1L, false, 0L );
  118.     
  119.     OffsetRect( &rect, WWIDTH + 10, 0 );
  120.     gWindow = NewCWindow( 0L, &rect, "\pBandCopying ON - Padding OFF", true, documentProc,
  121.                             (WindowPtr)-1L, true, 0L );
  122.                             
  123.     SetPort( gCWindow );
  124. }
  125.  
  126. void createGWorld()
  127. {
  128.     /*int        i;*/
  129.     /*Rect    rect;*/
  130.     
  131.     /* Create a 1bit offscreen gWorld to be used for B/W dithering. */
  132.  
  133.     NewGWorld( &gGWorld, 1, &gWindow->portRect, nil, nil, 0 );
  134.     gPixMap = GetGWorldPixMap( gGWorld );
  135. }
  136.  
  137. void drawCWindow()
  138. {
  139.     Rect    rect;
  140.     int        row;
  141.     
  142.     /* Reposition the picture's rect then draw it into the first window. */
  143.     
  144.     SetPort( gCWindow );
  145.     
  146.     rect.left = (WWIDTH - gPictWidth) / 2;
  147.     rect.top = (WHEIGHT - gPictHeight) / 2;
  148.     rect.right = rect.left + gPictWidth;
  149.     rect.bottom = rect.top + gPictHeight;
  150.     
  151.     DrawPicture( gPict, &rect );
  152.     
  153.     TextFont( helvetica );
  154.     TextSize( 12 );
  155.     
  156.     row = 20;    
  157.     drawMessage( &row, "\p• Click the mouse button in the" );
  158.     drawMessage( &row, "\p   b/w window to draw another band." );
  159.     drawMessage( &row, "\p• Press any key other than ESC to toggle between" );
  160.     drawMessage( &row, "\p   using band copying with or without padding." );
  161.     
  162.     row = 200;    
  163.     drawMessage( &row, "\p• Press ESC to toggle between using copybits" );
  164.     drawMessage( &row, "\p   with or without bands." );
  165. }
  166.  
  167. void drawMessage( row, string )
  168. int        *row;
  169. Str255    string;
  170. {
  171.     MoveTo( 10, *row += 15 );
  172.     DrawString(  string );
  173. }
  174.  
  175. void drawBwWindow()
  176. {
  177.     Rect rect;
  178.     
  179.     if (gPadding >= 0)
  180.     {
  181.         SetRect( &rect, 0, 0, gPictWidth * SCALING, (gBandHeight + gPadding) * SCALING );
  182.         UpdateGWorld( &gGWorld, 1, &rect, nil, nil, stretchPix );
  183.         gPixMap = GetGWorldPixMap( gGWorld );
  184.         doBandCopy();
  185.     }
  186.     else
  187.     {
  188.         UpdateGWorld( &gGWorld, 1, &gWindow->portRect, nil, nil, stretchPix );
  189.         gPixMap = GetGWorldPixMap( gGWorld );
  190.         doNoBandCopy();
  191.     }
  192. }
  193.  
  194. void doBandCopy()
  195. {
  196.     int            i;
  197.     int            hoffset, voffset;    /* Starting position of picture in b/w window. */
  198.     Rect        colorRect;            /* Source rect for the color image band. */
  199.     Rect        gworldRect;            /* Source/destinaton rect for the gworld image band. */
  200.     Rect        bwRect;                /* Destination rect for the b/w image band. */
  201.     CGrafPtr    currentPort;        /* CGrafPort of window. */
  202.     GDHandle    currentGDevice;        /* GDevice used by window. */
  203.     Str255        string;
  204.         
  205.     hoffset = (WWIDTH - gPictWidth) / 2;
  206.     voffset = (WHEIGHT - gPictHeight) / 2;
  207.  
  208.     SetPort( gWindow );
  209.     TextFont( helvetica );
  210.     TextSize( 9 );
  211.  
  212.     GetGWorld( ¤tPort, ¤tGDevice );
  213.  
  214.     for (i = gBandStart; i <= gBandEnd; i++)
  215.     {
  216.         SetGWorld( gGWorld, nil );
  217.  
  218.         /* Define the source band rect for the color image, */
  219.         /*    INCLUDING any padding if applicable.            */
  220.         colorRect.left = hoffset;
  221.         colorRect.right = hoffset + gPictWidth;
  222.         colorRect.top = voffset + (i * gBandHeight) - gPadding;
  223.         colorRect.bottom = voffset + (i * gBandHeight) + gBandHeight;
  224.         
  225.         /* Define the destination band rect for the gworld dithered image, */
  226.         /*    allow extra space for padding if necessary.                       */
  227.         SetRect( &gworldRect, 0, 0, gPictWidth * SCALING,
  228.                             (gBandHeight + gPadding) * SCALING );
  229.     
  230.         /* Copy the color source into the B/W gworld using dithering. */
  231.         /*  Also, be sure to copy any padded area as well.              */
  232.         CopyBits( &gCWindow->portBits, (BitMap*)*gPixMap, &colorRect, &gworldRect, ditherCopy, 0l);
  233.         
  234.         SetGWorld( currentPort, currentGDevice );
  235.         
  236.         /* Now, set the source band rect to the gworld image's EXCLUDING any padding. */
  237.         /*  If padding was used, offset pass the padding and down to the band.        */
  238.         SetRect( &gworldRect, 0, gPadding * SCALING, gPictWidth * SCALING,
  239.                                 (gPadding + gBandHeight) * SCALING );
  240.         
  241.         /* Define the destination band rect for the final b/w image. */
  242.         /*  No padding should apply here!!                             */
  243.         SetRect( &bwRect, hoffset / SCALING,
  244.                         (voffset / SCALING) + ((i * gBandHeight) * SCALING),
  245.                         (hoffset / SCALING) + (gPictWidth * SCALING),
  246.                         (voffset / SCALING) + (((i * gBandHeight) + gBandHeight) * SCALING) );
  247.  
  248.         /* Finally, copy the offscreen image into the B/W window. */
  249.         CopyBits( (BitMap*)*gPixMap, &gWindow->portBits, &gworldRect, &bwRect, srcCopy, 0l);
  250.     
  251.         SetPort( gWindow );
  252.         MoveTo( bwRect.right + 3, bwRect.bottom );
  253.         NumToString( i, string );
  254.         DrawString( string );
  255.     }
  256. }
  257.  
  258. void doNoBandCopy()
  259. {
  260.     Rect        colorRect;            /* Source rect for the color image band. */
  261.     /*Rect        gworldRect;            /* Source/destinaton rect for the gworld image band. */
  262.     Rect        bwRect;                /* Destination rect for the b/w image band. */
  263.     int            hoffset, voffset;    /* Starting position of picture in b/w window. */
  264.     CGrafPtr    currentPort;        /* CGrafPort of window. */
  265.     GDHandle    currentGDevice;        /* GDevice used by window. */
  266.     
  267.     GetGWorld( ¤tPort, ¤tGDevice );
  268.     
  269.     hoffset = (WWIDTH - gPictWidth) / 2;
  270.     voffset = (WHEIGHT - gPictHeight) / 2;
  271.  
  272.     colorRect.left = hoffset;
  273.     colorRect.top = voffset;
  274.     colorRect.right = hoffset + gPictWidth;
  275.     colorRect.bottom = voffset + gPictHeight;
  276.  
  277.     SetRect( &bwRect, hoffset / SCALING,
  278.                     voffset / SCALING,
  279.                     (hoffset / SCALING) + (gPictWidth * SCALING),
  280.                     (voffset / SCALING) + (gPictHeight * SCALING) );
  281.     
  282.     SetGWorld( gGWorld, nil );
  283.     CopyBits( &gCWindow->portBits, (BitMap*)*gPixMap, &colorRect, &bwRect, ditherCopy, 0l);
  284.     SetGWorld( currentPort, currentGDevice );
  285.     CopyBits( (BitMap*)*gPixMap, &gWindow->portBits, &bwRect, &bwRect, srcCopy, 0l);
  286. }
  287.  
  288. void doEventLoop()
  289. {
  290.     EventRecord event;
  291.     WindowPtr   window;
  292.     short       clickArea;
  293.     Rect        screenRect;
  294.     static int    oldPadding;
  295.     
  296.     for (;;)
  297.     {
  298.         if (WaitNextEvent( everyEvent, &event, 0, nil ))
  299.         {
  300.             if (event.what == mouseDown)
  301.             {
  302.                 clickArea = FindWindow( event.where, &window );
  303.                 
  304.                 if (clickArea == inDrag)
  305.                 {
  306.                     screenRect = (**GetGrayRgn()).rgnBBox;
  307.                     DragWindow( window, event.where, &screenRect );
  308.                 }
  309.                 else if (clickArea == inContent)
  310.                 {
  311.                     if (window != FrontWindow())
  312.                         SelectWindow( window );
  313.                     else
  314.                     {
  315.                         if (gPadding >= 0)
  316.                         {    
  317.                             gBandEnd++;
  318.                             
  319.                             if (gBandEnd > TOTALBANDS)
  320.                             {
  321.                                 gBandEnd = 0;
  322.                                 SetPort( gWindow );
  323.                                 EraseRect( &gWindow->portRect );
  324.                             }
  325.                             
  326.                             gBandStart = gBandEnd;
  327.                             drawBwWindow();
  328.                         }
  329.                     }
  330.                 }
  331.                 else if (clickArea == inGoAway)
  332.                     if (TrackGoAway( window, event.where ))
  333.                         return;
  334.             }
  335.             else if (event.what == keyDown || event.what == autoKey)
  336.             {
  337.                 if ((event.message & charCodeMask) == 0x1b)
  338.                 {
  339.                     SetPort( gWindow );
  340.                     EraseRect( &gWindow->portRect );
  341.                     
  342.                     if (gPadding >= 0)
  343.                         gPadding = -1;
  344.                     else
  345.                         gPadding = oldPadding;
  346.                 }
  347.                 
  348.                 if (gPadding == 0)
  349.                 {
  350.                     gPadding = PADHEIGHT;
  351.                     SetWTitle( gWindow, "\pBandCopying ON - Padding ON" );
  352.                     oldPadding = 0;
  353.                 }
  354.                 else if (gPadding > 0)
  355.                 {
  356.                     gPadding = 0;
  357.                     SetWTitle( gWindow, "\pBandCopying ON - Padding OFF" );
  358.                     oldPadding = PADHEIGHT;
  359.                 }
  360.                 else
  361.                     SetWTitle( gWindow, "\pBandCopying OFF" );
  362.                     
  363.                 gBandStart = 0;
  364.                 drawBwWindow();
  365.             }
  366.             
  367.             else if (event.what == updateEvt)
  368.             {
  369.                 window = (WindowPtr)event.message;    
  370.                 SetPort( window );
  371.                 
  372.                 BeginUpdate( window );
  373.                 
  374.                 gBandStart = 0;
  375.                 drawCWindow();
  376.                 drawBwWindow();
  377.                 
  378.                 EndUpdate( window );
  379.             }
  380.         }
  381.     }
  382. }